module Decoder(

	input			i_DC_valid,
	input	[31:0]	i_DC_Inst,
	input			i_DC_EXL,
	input			i_DC_BranchDelaySlot,
	
	output	[4:0]	o_DC_alcode,
	output	[4:0]	o_DC_bjcode,
	output	[4:0]	o_DC_iecode,
	output	[4:0]	o_DC_mvcode,
	output	[4:0]	o_DC_mdcode,
	output	[4:0]	o_DC_memcode,
	output	[7:0]	o_DC_EXCCODE,	//{[7]valid, [6]isERET, [5]isDelaySlot, [4:0]ExcCode}
	output	[4:0]	o_DC_regsrc1,
	output	[4:0]	o_DC_regsrc2,
	output	[4:0]	o_DC_regdes
	
);

	wire	[5:0]	opcode 	= i_DC_Inst[31:26];
	wire	[4:0]	sa 		= i_DC_Inst[10:6];
	wire	[5:0]	func	= i_DC_Inst[5:0];
	//regsrc and regdes
	wire	[4:0]	rs	= i_DC_Inst[25:21];
	wire	[4:0]	rt	= i_DC_Inst[20:16];
	wire	[4:0]	rd	= i_DC_Inst[15:11];
	
	wire	ADD		= (opcode==6'b000000 && sa==5'b00000 && func==6'b100000);
	wire	ADDI	= (opcode==6'b001000);
	wire	ADDU	= (opcode==6'b000000 && sa==5'b00000 && func==6'b100001);
	wire	ADDIU	= (opcode==6'b001001);
	wire	SLT		= (opcode==6'b000000 && sa==5'b00000 && func==6'b101010);
	wire	SLTI	= (opcode==6'b001010);
	wire	SLTU	= (opcode==6'b000000 && sa==5'b00000 && func==6'b101011);
	wire	SLTIU	= (opcode==6'b001011);
	wire	AND		= (opcode==6'b000000 && sa==5'b00000 && func==6'b100100);
	wire	ANDI	= (opcode==6'b001100);
	wire	OR		= (opcode==6'b000000 && sa==5'b00000 && func==6'b100101);
	wire	ORI		= (opcode==6'b001101);
	wire	XOR		= (opcode==6'b000000 && sa==5'b00000 && func==6'b100110);
	wire	XORI	= (opcode==6'b001110);
	wire	NOR		= (opcode==6'b000000 && sa==5'b00000 && func==6'b100111);
	wire	LUI		= (opcode==6'b001111 && rs==5'b00000);
	wire	SLL		= (opcode==6'b000000 && rs==5'b00000 && func==6'b000000);
	wire	SLLV	= (opcode==6'b000000 && sa==5'b00000 && func==6'b000100);
	wire	SRA		= (opcode==6'b000000 && rs==5'b00000 && func==6'b000011);
	wire	SRAV	= (opcode==6'b000000 && sa==5'b00000 && func==6'b000111);
	wire	SRL		= (opcode==6'b000000 && rs==5'b00000 && func==6'b000010);
	wire	SRLV	= (opcode==6'b000000 && sa==5'b00000 && func==6'b000110);
	wire	SUB		= (opcode==6'b000000 && sa==5'b00000 && func==6'b100010);
	wire	SUBU	= (opcode==6'b000000 && sa==5'b00000 && func==6'b100011);
	wire	CLO		= (0);
	wire	CLZ		= (0);
	wire	LW		= (opcode==6'b100011);
	wire	LW		= (0);
	wire	LWL		= (0);
	wire	LWR		= (0);
	wire	SW		= (opcode==6'b101011);
	wire	SC		= (0);
	wire	SWL		= (0);
	wire	SWR		= (0);
	wire	LH		= (opcode==6'b100001);
	wire	LB		= (opcode==6'b100000);
	wire	LHU		= (opcode==6'b100101);
	wire	LBU		= (opcode==6'b100100);
	wire	SH		= (opcode==6'b101001);
	wire	SB		= (opcode==6'b101000);
	wire	PREF	= (0);
	wire	SYNC	= (0);
	wire	TLBP	= (0);
	wire	TLBR	= (0);
	wire	TLBWI	= (0);
	wire	TLBWR	= (0);
	wire	CACHE	= (0);
	wire	BEQ		= (opcode==6'b000100);
	wire	BGTZ	= (opcode==6'b000111 && rt==5'b00000);
	wire	BGEZ	= (opcode==6'b000001 && rt==5'b00001);
	wire	BGEZAL	= (opcode==6'b000001 && rt==5'b10001);
	wire	BNE		= (opcode==6'b000101);
	wire	BLEZ	= (opcode==6'b000110 && rt==5'b00000);
	wire	BLTZ	= (opcode==6'b000001 && rt==5'b00000);
	wire	BLEZAL	= (opcode==6'b000001 && rt==5'b10000);
	wire	BEQL	= (0);
	wire	BGTZL	= (0);
	wire	BGEZL	= (0);
	wire	BGEZALL	= (0);
	wire	BNEL	= (0);
	wire	BLEZL	= (0);
	wire	BLTZL	= (0);
	wire	BLEZALL	= (0);
	wire	J		= (opcode==6'b000010);
	wire	JAL		= (opcode==6'b000011);
	wire	JR		= (opcode==6'b000000 && rt==5'b00000 && rd==5'b00000 && sa==5'b00000 && func==6'b001000);
	wire	JALR	= (opcode==6'b000000 && rt==5'b00000 && sa==5'b00000 && func==6'b001001);
	wire	TEQ		= (0);
	wire	TEQI	= (0);
	wire	TNE		= (0);
	wire	TNEI	= (0);
	wire	TGE		= (0);
	wire	TGEI	= (0);
	wire	TGEU	= (0);
	wire	TGEIU	= (0);
	wire	TLT		= (0);
	wire	TLTI	= (0);
	wire	TLTU	= (0);
	wire	TLTIU	= (0);
	wire	BREAK	= (opcode==6'b000000 && func==6'b001101);
	wire	SYSCALL	= (opcode==6'b000000 && func==6'b001100);
	wire	ERET	= (i_DC_Inst==32'b000000_1_0000000000000000000_011000);
	wire	WAIT	= (0);
	wire	MFHI	= (opcode==6'b000000 && rs==5'b00000 && rt==5'b00000 && sa==5'b00000 && func==6'b010000);
	wire	MFLO	= (opcode==6'b000000 && rs==5'b00000 && rt==5'b00000 && sa==5'b00000 && func==6'b010010);
	wire	MTHI	= (opcode==6'b000000 && rt==5'b00000 && rd==5'b00000 && sa==5'b00000 && func==6'b010001);
	wire	MTLO	= (opcode==6'b000000 && rt==5'b00000 && rd==5'b00000 && sa==5'b00000 && func==6'b010011);
	wire	MFC0	= (opcode==6'b010000 && rs==5'b00000 && i_DC_Inst[10:2]==8'b00000000);
	wire	MTC0	= (opcode==6'b010000 && rs==5'b00100 && i_DC_Inst[10:2]==8'b00000000);
	wire	MOVZ	= (0);
	wire	MOVN	= (0);
	wire	MOVT	= (0);
	wire	MOVF	= (0);
	wire	MULT	= (opcode==6'b000000 && rd==5'b00000 && sa==5'b00000 && func=6'b011000);
	wire	MULTU	= (opcode==6'b000000 && rd==5'b00000 && sa==5'b00000 && func=6'b011001);
	wire	DIV		= (opcode==6'b000000 && rd==5'b00000 && sa==5'b00000 && func=6'b011010);
	wire	DIVU	= (opcode==6'b000000 && rd==5'b00000 && sa==5'b00000 && func=6'b011011);
	wire	MADD	= (0);
	wire	MADDU	= (0);
	wire	MSUB	= (0);
	wire	MSUBU	= (0);
	wire	MUL		= (0);
	
	assign	o_DC_regsrc1 = (ADD		|ADDI	|ADDU	|ADDIU	|SUB	|SUBU	|SLT	|SLTI	|
							SLTU	|SLTIU	|DIV	|DIVU	|MULT	|MULTU	|AND	|ANDI	|
							NOR		|OR		|ORI	|XOR	|XORI	|SLLV	|SRAV	|SRLV	|
							BEQ		|BGEZ	|BGTZ	|BLEZ	|BLTZ	|BGEZAL	|BLTZAL	|JR		|
							JALR	|MTHI	|MTLO	|LB		|LBU	|LH		|LHU	|LW		|
							SB		|SH		|SW		) ? rs : 5'd0;
	assign	o_DC_regsrc2 = (ADD		|ADDU	|SUB	|SUBU	|SLT	|SLTU	|DIV	|DIVU	|
							MULT	|MULTU	|AND	|LUI	|NOR	|OR		|XOR	|SLLV	|
							SLL		|SRAV	|SRA	|SRLV	|SRL	|BNE	|SB		|SH		|
							SW		|MTC0	) ? rt : 5'd0;
	
	wire	[4:0]	regdes_rd 	= ( ADD		|ADDU	|SUB	|SUBU	|SLT	|SLTU	|AND	|NOR	|
									OR		|XOR	|SLLV	|SLL	|SRAV	|SRA	|SRLV	|SRL	|
									JALR	|MFHI	|MFLO	) ? rd : 5'd0;
	wire	[4:0]	regdes_rt 	= ( ADDI	|ADDIU	|SLTI	|SLTIU	|ANDI	|LUI	|ORI	|XORI	|
									MFC0	|LB		|LBU	|LH		|LHU	|LW		) ? rt : 5'd0;			
	wire	[4:0]	regdes_31 	= ( BGEZAL	|BLTZAL	|JAL ) ? 5'd31 	: 5'd0;
	
	assign	o_DC_regdes = regdes_rd | regdes_rt | regdes_31;
	
	wire	[4:0]	Ex_Sys 	= (SYSCALL) ? 4'h8 : 4'd0;
	wire	[4:0]	Ex_BP 	= (BREAK) ? 4'h9 : 4'd0;
	assign	o_DC_EXCCODE[7] = SYSCALL | BREAK;
	assign	o_DC_EXCCODE[6] = ERET;
	assign	o_DC_EXCCODE[5] = i_DC_BranchDelaySlot;
	assign	o_DC_EXCCODE[4:0] = Ex_Sys | Ex_BP;
	
	assign	o_DC_alcode[0] = ADD 	|ADDU 	|SLT 	|SLTU 	|AND 	|OR 	|XOR 	|NOR 	|SLL 	|SRA 	|SRL 	|SUB 	|CLO;
	assign	o_DC_alcode[1] = ADDI 	|ADDU 	|SLTI 	|SLTU 	|ANDI 	|OR 	|XORI 	|NOR 	|SLLV 	|SRA 	|SRLV 	|SUB 	|CLZ;
	assign	o_DC_alcode[2] = ADDIU 	|SLT 	|SLTI 	|SLTU 	|ORI 	|XOR 	|XORI 	|NOR 	|SRAV 	|SRL 	|SRLV 	|SUB;
	assign	o_DC_alcode[3] = SLTIU 	|AND 	|ANDI 	|OR 	|ORI 	|XOR 	|XORI 	|NOR	|SUBU 	|CLO 	|CLZ;
	assign	o_DC_alcode[4] = LUI 	|SLL 	|SLLV 	|SRA 	|SRAV 	|SRL 	|SRLV 	|SUB 	|SUBU 	|CLO 	|CLZ;
	
	assign	o_DC_memcode[0] = LW	|LWL	|SW		|SWL	|LH		|LHU	|SH		|PREF	|TLBP	|TLBWI	|CACHE;
	assign	o_DC_memcode[1] = LL	|LWL	|SC		|SWL	|LB		|LHU	|SB		|PREF	|TLBR	|TLBWI;
	assign	o_DC_memcode[2] = LWR	|SW		|SC		|SWL	|LBU	|SH		|SB		|PREF	|TLBWI	|CACHE;
	assign	o_DC_memcode[3] = SWR	|LH		|LB		|LHU	|LBU	|SH		|SB		|PREF;
	assign	o_DC_memcode[4] = SYNC	|TLBP	|TLBR	|TLBWI	|TLBWR	|CACHE;
	
	assign	o_DC_bjcode[0] = BEQ	|BGEZ	|BNE	|BLTZ	|BEQL	|BGEZL	|BNEL	|BLTZL	|J		|JR;
	assign	o_DC_bjcode[1] = BGTZ	|BGEZ	|BLEZ	|BLTZ	|BGTZL	|BGEZL	|BLEZL	|BLTZL	|JAL	|JALR;
	assign	o_DC_bjcode[2] = BGEZAL	|BNE	|BLEZ	|BLTZ	|BGEZALL|BNEL	|BLEZL	|BLTZL	|JALR;
	assign	o_DC_bjcode[3] = BLTZAL	|BEQL	|BGTZL	|BGEAL	|BGEZALL|BNEL	|BLEZL	|BLTZL;
	assign	o_DC_bjcode[4] = BLTZALL|J		|JAL	|JR		|JALR;
	
	assign	o_DC_iecode[0] = TEQ 	|TNE	|TGE	|TGEU	|TLT	|TLTU	|BREAK	|ERET;
	assign	o_DC_iecode[1] = TEQI	|TNE	|TGEI	|TGEU	|TLTI	|TLTU	|SYSCALL|REET;
	assign	o_DC_iecode[2] = TNEI	|TGE	|TGEI	|TGEU	|TLTIU	|BREAK	|SYSCALL|REET;
	assign	o_DC_iecode[3] = TGEIU	|TLT	|TLTI	|TLTU	|TLTIU	|BREAK	|SYSCALL|REET;
	assign	o_DC_iecode[4] = WAIT;
	
	assign	o_DC_mvcode[0] = MFHI	|MTHI	|MFC0	|MOVZ	|MOVT;
	assign	o_DC_mvcode[1] = MFLO	|MTHI	|MTC0	|MOVZ	|MOVF;
	assign	o_DC_mvcode[2] = MTLO	|MFC0	|MTC0	|MOVZ;
	assign	o_DC_mvcode[3] = MOVN	|MOVT	|MOVF;
	assign	o_DC_mvcode[4] = 1'b0;
	
	assign	o_DC_mdcode[0] = MULT	|DIV	|MADD	|MSUB	|MUL;
	assign	o_DC_mdcode[1] = MULTU	|DIV	|MADDU	|MSUB;
	assign	o_DC_mdcode[2] = DIVU	|MADD	|MADDU	|MSUB;
	assign	o_DC_mdcode[3] = MSUBU	|MUL;
	assign	o_DC_mdcode[4] = 1'b0;
	
/*

		a4	 a3	  a2   a1	a0	alcode		memcode		bjcode		iecode		mvcode		mdcode

0:      0    0    0    0    0	
1:      0    0    0    0    1	01:ADD		01:LW		01:BEQ		01:TEQ		01:MFHI		01:MULT
2:      0    0    0    1    0	02:ADDI		02:LL		02:BGTZ		02:TEQI		02:MFLO		02:MULTU
3:      0    0    0    1    1	03:ADDU		03:LWL		03:BGEZ		03:TNE		03:MTHI		03:DIV
4:      0    0    1    0    0	04:ADDIU	04:LWR		04:BGEZAL	04:TNEI		04:MTLO		04:DIVU
5:      0    0    1    0    1	05:SLT		05:SW		05:BNE		05:TGE		05:MFC0		05:MADD
6:      0    0    1    1    0	06:SLTI		06:SC		06:BLEZ		06:TGEI		06:MTC0		06:MADDU
7:      0    0    1    1    1	07:SLTU		07:SWL		07:BLTZ		07:TGEU		07:MOVZ		07:MSUB
8:      0    1    0    0    0	08:SLTIU	08:SWR		08:BLTZAL	08:TGEIU	08:MOVN		08:MSUBU
9:      0    1    0    0    1	09:AND		09:LH		09:BEQL		09:TLT		09:MOVT		09:MUL
10:     0    1    0    1    0	10:ANDI		10:LB		10:BGTZL	10:TLTI		10:MOVF		
11:     0    1    0    1    1	11:OR		11:LHU		11:BGEZL	11:TLTU		
12:     0    1    1    0    0	12:ORI		12:LBU		12:BGEZALL	12:TLTIU	
13:     0    1    1    0    1	13:XOR		13:SH		13:BNEL		13:BREAK	
14:     0    1    1    1    0	14:XORI		14:SB		14:BLEZL	14:SYSCALL	
15:     0    1    1    1    1	15:NOR		15:PREF		15:BLTZL	15:ERET		
16:     1    0    0    0    0	16:LUI		16:SYNC		16:BLTZALL	16:WAIT		
17:     1    0    0    0    1	17:SLL		17:TLBP		17:J		
18:     1    0    0    1    0	18:SLLV		18:TLBR		18:JAL		
19:     1    0    0    1    1	19:SRA		19:TLBWI	19:JR		
20:     1    0    1    0    0	20:SRAV		20:TLBWR	20:JALR		
21:     1    0    1    0    1	21:SRL		21:CACHE	
22:     1    0    1    1    0	22:SRLV
23:     1    0    1    1    1	23:SUB
24:     1    1    0    0    0	24:SUBU
25:     1    1    0    0    1	25:CLO
26:     1    1    0    1    0	26:CLZ
27:     1    1    0    1    1	
28:     1    1    1    0    0	
29:     1    1    1    0    1	
30:     1    1    1    1    0	
31:     1    1    1    1    1

*/
	

endmodule